import React, { memo, useCallback, useContext, useMemo, useRef } from "react";
import { arrayMove } from "@dnd-kit/sortable";
import {
  DeleteOutlined,
  ArrowUpOutlined,
  ArrowDownOutlined,
} from "@ant-design/icons";
import { Modal, Button } from "antd";
import { useHover } from "ahooks";
import classNames from "classnames";
import update from "immutability-helper";
import FunFormCtx from "../../core";
import useRowSetting from "./rowSetting";
import LableSet from "./lableSet";
import RowRender from "./rowRender";
import styles from "../index.module.less";

interface CardProps {
  info: FunFormCard;
  couldDelete: boolean;
  couldMoveUp: boolean;
  couldMoveDown: boolean;
  gIndex: number;
  cIndex: number;
}

export default memo(
  ({
    info,
    couldDelete,
    couldMoveUp,
    couldMoveDown,
    gIndex,
    cIndex,
  }: CardProps) => {
    const { instance, updateInstance, activedElement, setActivedElement } =
      useContext(FunFormCtx);

    const {
      insertRow,
      deleteRow,
      insertCol,
      deleteCol,
      mergeCancel,
      mergeColumn,
      createByCategory,
      updateRow,
      moveColumnWidget,
      onWidgetMoveIn,
      deleteColWidget,
    } = useRowSetting();

    const ref = useRef(null);

    const isHovering = useHover(ref);

    const showBtns = useMemo(
      () => couldMoveUp || couldMoveDown,
      [couldMoveDown, couldMoveUp]
    );

    const onDeleteCard = useCallback(() => {
      Modal.confirm({
        content: "是否删除？",
        onOk() {
          updateInstance(
            update(instance, {
              groups: {
                [gIndex]: {
                  cards: {
                    $splice: [[cIndex, 1]],
                  },
                },
              },
            })
          );
          if (activedElement?.element?.uuid === info?.uuid) {
            setActivedElement(undefined);
          }
        },
      });
    }, [
      instance,
      gIndex,
      cIndex,
      activedElement,
      updateInstance,
      info.uuid,
      setActivedElement,
    ]);

    const onMoveCard = useCallback(
      (type: 1 | -1) => {
        updateInstance(
          update(instance, {
            groups: {
              [gIndex]: {
                cards: (list) => {
                  return arrayMove(list, cIndex, cIndex + type);
                },
              },
            },
          })
        );
      },
      [instance, gIndex, cIndex, updateInstance]
    );

    return (
      <div
        className={classNames(
          styles.card,
          isHovering && styles.isHovering,
          activedElement?.element?.uuid === info.uuid && styles.actived
        )}
        onClick={() => {
          setActivedElement({
            element: info,
            position: {
              groupIndex: gIndex,
              cardIndex: cIndex,
              rowIndex: 0,
              colIndex: 0,
            },
          });
        }}
      >
        <div className={styles.cardTitle} ref={ref}>
          <div className={styles.container}>
            <div className={styles.left}>{info.title}</div>
            <div className={styles.right}>
              {showBtns && (
                <Button.Group>
                  <Button
                    disabled={!couldMoveUp}
                    icon={<ArrowUpOutlined />}
                    onClick={(e) => {
                      e.stopPropagation();
                      onMoveCard(-1);
                    }}
                    type="link"
                  ></Button>
                  <Button
                    type="link"
                    disabled={!couldMoveDown}
                    icon={<ArrowDownOutlined />}
                    onClick={(e) => {
                      e.stopPropagation();
                      onMoveCard(1);
                    }}
                  ></Button>
                </Button.Group>
              )}
            </div>
          </div>

          {couldDelete && isHovering && (
            <div className={styles.deleteIcon} onClick={onDeleteCard}>
              <DeleteOutlined />
            </div>
          )}
        </div>
        <div className={styles.cardBody}>
          {info.mode === "horizontal" && (
            <LableSet
              info={info}
              onChange={(val, i) => {
                updateInstance(
                  update(instance, {
                    groups: {
                      [gIndex]: {
                        cards: {
                          [cIndex]: {
                            labelWidths: {
                              [i]: {
                                $set: val,
                              },
                            },
                          },
                        },
                      },
                    },
                  })
                );
              }}
            />
          )}

          {info.rows.map((row, i, { length }) => {
            return (
              <RowRender
                couldDelete={length !== 1}
                key={row.uuid}
                info={row}
                mode={info.mode}
                labelWidths={info.labelWidths}
                onInsertRow={(type) => {
                  insertRow(
                    {
                      groupIndex: gIndex,
                      cardIndex: cIndex,
                      rowIndex: i,
                    },
                    type
                  );
                }}
                onDeleteRow={() =>
                  deleteRow({
                    groupIndex: gIndex,
                    cardIndex: cIndex,
                    rowIndex: i,
                  })
                }
                onInsertCol={(colIndex, type) => {
                  insertCol(
                    {
                      groupIndex: gIndex,
                      cardIndex: cIndex,
                      colIndex,
                    },
                    type
                  );
                }}
                onDeleteCol={(colIndex) => {
                  deleteCol({
                    groupIndex: gIndex,
                    cardIndex: cIndex,
                    colIndex,
                  });
                }}
                onMergeColumn={(colIndex) => {
                  mergeColumn({
                    groupIndex: gIndex,
                    cardIndex: cIndex,
                    rowIndex: i,
                    colIndex,
                  });
                }}
                onMergeCancel={(colIndex) => {
                  mergeCancel({
                    groupIndex: gIndex,
                    cardIndex: cIndex,
                    rowIndex: i,
                    colIndex,
                  });
                }}
                onCreateByCategory={(colIndex, category) => {
                  createByCategory({
                    groupIndex: gIndex,
                    cardIndex: cIndex,
                    rowIndex: i,
                    colIndex,
                    category,
                  });
                }}
                onUpdateRow={(row) => {
                  updateRow(row, {
                    groupIndex: gIndex,
                    cardIndex: cIndex,
                    rowIndex: i,
                  });
                }}
                onMoveColunmWidget={(el, to) => {
                  moveColumnWidget(el, to, gIndex);
                }}
                onMoveWidgetIn={(widget, colId, at) => {
                  onWidgetMoveIn(
                    widget,
                    colId,
                    {
                      groupIndex: gIndex,
                      cardIndex: cIndex,
                      rowIndex: i,
                    },
                    at
                  );
                }}
                onSelect={(colIndex) => {
                  const widget = row.columns[colIndex].widget;
                  if (!widget) return;
                  setActivedElement({
                    element: widget,
                    position: {
                      groupIndex: gIndex,
                      cardIndex: cIndex,
                      rowIndex: i,
                      colIndex,
                    },
                  });
                }}
                onDeleteWidget={(colIndex) => {
                  deleteColWidget({
                    groupIndex: gIndex,
                    cardIndex: cIndex,
                    rowIndex: i,
                    colIndex,
                  });
                }}
              ></RowRender>
            );
          })}
        </div>
      </div>
    );
  }
);
